#ifndef xpack_math_exp10
#define xpack_math_exp10
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::math_exp10::inc
#include"define/base_type.hpp"
#include"define/inf.hpp"
#include"macro/xexport.hpp"
#include"meta/is_same.hpp"
#pragma pop_macro("xuser")

namespace mixc::math_exp10{
    constexpr f64 f64_lut_1e0_1e15[]     = { 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, };
    constexpr f64 f64_lut_1e16_1e240[]   = { 1e0, 1e16, 1e32, 1e48, 1e64, 1e80, 1e96, 1e112, 1e128, 1e144, 1e160, 1e176, 1e192, 1e208, 1e224, 1e240};
    constexpr f64 f64_lut_1e256[]        = { 1e0, 1e256 };

    constexpr f32 f32_lut_1e0_1e38[]    = {
        1e00f, 1e01f, 1e02f, 1e03f, 1e04f, 1e05f, 1e06f, 1e07f, 1e08f, 1e09f,
        1e10f, 1e11f, 1e12f, 1e13f, 1e14f, 1e15f, 1e16f, 1e17f, 1e18f, 1e19f,
        1e20f, 1e21f, 1e22f, 1e23f, 1e24f, 1e25f, 1e26f, 1e27f, 1e28f, 1e29f,
        1e30f, 1e31f, 1e32f, 1e33f, 1e34f, 1e35f, 1e36f, 1e37f, 1e38f,
    };
}

namespace mixc::math_exp10::origin{
    template<class f64_t>
    requires(inc::is_same<f64_t, f64>)
    inline f64 exp10_unsafe(uxx x){
        union {
            struct{
                uxx low : 4;
                uxx mid : 4;
                uxx hig : 1;
            };
            uxx full;
        }w;

        w.full    = x;
        return f64_lut_1e0_1e15[w.low] * f64_lut_1e16_1e240[w.mid] * f64_lut_1e256[w.hig];
    }

    template<class f64_t>
    requires(inc::is_same<f64_t, f64>)
    inline f64 exp10(uxx x){
        if (x > 308){
            return inc::inf_pos;
        }
        return exp10_unsafe<f64>(x);
    }

    template<class f32_t>
    requires(inc::is_same<f32_t, f32>)
    inline f32 exp10_unsafe(uxx x){
        return f32_lut_1e0_1e38[x];
    }

    template<class f32_t>
    requires(inc::is_same<f32_t, f32>)
    inline f32 exp10(uxx x){
        if (x > 38){
            return f32(inc::inf_pos);
        }
        return exp10_unsafe<f32>(x);
    }
}

#endif

xexport_space(mixc::math_exp10::origin)